use parking_lot::Mutex;
use pipelines::{Sender,Receiver};
use util::FingerPrintHasher;

use std::sync::Arc;
use std::time::Instant;

use super::super::read::ChunkerProduct;

use crate::backup::{BackupStatistics, BackupResult};
use crate::chunk::Chunk;
use crate::constants::DefaultFingerprintType;
use crate::recipe::file::FileInfo;

pub struct ChunkHasher {
	statistics:Arc<Mutex<BackupStatistics>>,
}

impl ChunkHasher {
	pub fn new(statistics:Arc<Mutex<BackupStatistics>>) -> Self {
		Self {
			statistics:statistics,
		}
	}
	
	pub fn hash(&self,out:&Sender<HasherProduct>,recv:Receiver<ChunkerProduct>) -> BackupResult<()> {
		let mut cost_time = 0;
		for chunker_product in recv {
			match chunker_product {
				ChunkerProduct::FileInfo(info) => {
					out.send(HasherProduct::FileInfo(info));
				}
				ChunkerProduct::ChunkPointer(cp) => {
					let now = Instant::now();
					let fp = DefaultFingerprintType::fp(&cp);
					cost_time += now.elapsed().as_micros();
					out.send(HasherProduct::Chunk(Arc::new(Chunk::new(cp,fp))));
				}
			}
		}
		self.statistics.lock().set_hash_phase_time(cost_time);
		Ok(())
	}
}

pub enum HasherProduct {
	FileInfo(FileInfo),
	Chunk(Arc<Chunk>),
}
